﻿//--------------------------------------------------------------------
// 动态报表页表格件 v1.00
//
// 开发人： 朱明智
// 创建时间： 2019-08-22
//
// 修改人：
// 修改时间：
//--------------------------------------------------------------------
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System;
using System.Data;
using System.Text;

namespace Dynamic.Controller
{
    public class Tablix : ReportController
    {
        #region DocTemplate

        private const string fieldsTemp =
        "<Field Name=\"{0}\">" +
        "   <DataField>{0}</DataField>" +
        "<rd:TypeName>System.String</rd:TypeName></Field>";

        private const string tablixHeaderTemp =
        "<TablixCell>" +
        "    <CellContents>" +
        "        <Textbox Name=\"Textbox{0}{1}\">" +
        "            <CanGrow>true</CanGrow>" +
        "            <KeepTogether>true</KeepTogether>" +
        "            <Paragraphs>" +
        "                <Paragraph>" +
        "                    <TextRuns>" +
        "                        <TextRun>" +
        "                            <Value>{2}</Value>" +
        "                            <Style>" +
        "                                <FontFamily>{4}</FontFamily>" +
        "                            </Style>" +
        "                        </TextRun>" +
        "                    </TextRuns>" +
        "                    <Style>" +
        "                        <TextAlign>Center</TextAlign>" +
        "                    </Style>" +
        "                </Paragraph>" +
        "            </Paragraphs>" +
        "            <rd:DefaultName>Textbox{0}{1}</rd:DefaultName>" +
        "            <Visibility>" +
        "                <Hidden>{5}</Hidden>" +
        "            </Visibility>" +
        "            <Style>" +
        "                <Border>" +
        "                    <Color>Black</Color>" +
        "                    <Style>Solid</Style>" +
        "                </Border>{3}" +
        "                <PaddingLeft>2pt</PaddingLeft>" +
        "                <PaddingRight>2pt</PaddingRight>" +
        "                <PaddingTop>2pt</PaddingTop>" +
        "                <PaddingBottom>2pt</PaddingBottom>" +
        "            </Style>" +
        "        </Textbox>" +
        "    </CellContents>" +
        "</TablixCell>";

        private const string tablixCellTemp =
        "<TablixCell>" +
        "    <CellContents>" +
        "        <Textbox Name=\"{0}{1}1\">" +
        "            <CanGrow>true</CanGrow>" +
        "            <KeepTogether>true</KeepTogether>" +
        "            <Paragraphs>" +
        "                <Paragraph>" +
        "                    <TextRuns>" +
        "                        <TextRun>" +
        "                            <Value>=Fields!{0}.Value</Value>" +
        "                             <Style>" +
        "                                <FontFamily>{3}</FontFamily>" +
        "                            </Style>" +
        "                        </TextRun>" +
        "                    </TextRuns>" +
        "                    <Style>" +
        "                        <TextAlign>{2}</TextAlign>" +
        "                    </Style>" +
        "                </Paragraph>" +
        "            </Paragraphs>" +
        "            <rd:DefaultName>{0}{1}1</rd:DefaultName>" +
        "            <Style>" +
        "                <Border>" +
        "                    <Color>Black</Color>" +
        "                    <Style>Solid</Style>" +
        "                </Border>" +
        "                <PaddingLeft>2pt</PaddingLeft>" +
        "                <PaddingRight>2pt</PaddingRight>" +
        "                <PaddingTop>2pt</PaddingTop>" +
        "                <PaddingBottom>2pt</PaddingBottom>" +
        "            </Style>" +
        "        </Textbox>" +
        "    </CellContents>" +
        "</TablixCell>";
        #endregion

        private DataTable data;

        /// <summary>
        /// 列头样式
        /// </summary>
        private readonly IEnumerable<ReportColumnStyle> coloumStyle = new List<ReportColumnStyle>();

        private List<ReportItemPattern> _reportItemPatterns = new List<ReportItemPattern>();

        private List<ReportItemPattern> _reportHeadPatterns = new List<ReportItemPattern>();

        public Tablix()
        {
            //template = TemplateHelper.TablixTemp;
        }

        /// <summary>
        /// 添加列表类型的数据源
        /// </summary>
        /// <typeparam name="T">元素类型</typeparam>
        /// <param name="data">迭代类型</param>
        public void AddData<T>(IEnumerable<T> data)
        {
            if (data.Count() > 0)
            {
                this.data = new DataTable();
                var props = typeof(T).GetProperties();
                foreach (var item in props)
                {
                    this.data.Columns.Add(new DataColumn()
                    {
                        ColumnName = item.Name,
                        DataType = item.PropertyType,
                    });
                }

                foreach (var item in data)
                {
                    object[] row = new object[props.Length];
                    for (int i = 0; i < props.Length; i++)
                    {
                        row[i] = props[i].GetValue(item, null);
                    }
                    this.data.Rows.Add(row);
                }
            }
        }

        public void AddData(DataTable data)
        {
            this.data = data;
        }

        private void AddReportItem()
        {
            var fields = new StringBuilder();
            var columns = new StringBuilder();
            var tablixHearders = new StringBuilder();
            var tablixCells = new StringBuilder();
            var tablixMembers = new StringBuilder();

            // table宽
            float tableWidth = 0f;

            // 固定列宽的列
            List<ReportColumnStyle> fixCols = new List<ReportColumnStyle>();
            foreach (var colStyle in coloumStyle)
            {
                foreach (DataColumn col in data.Columns)
                {
                    if (colStyle.ColumnWidth > 0f && colStyle.ColumnName == col.ColumnName)
                    {
                        fixCols.Add(colStyle);
                    }
                }
            }
            // 所有固定列的宽和
            float fixColsSumWidth = fixCols.Sum(x => x.ColumnWidth);
            if (fixColsSumWidth > this.Report.Width)
            {
                throw new Exception("所指定的列宽大于纸张的宽(PageWidth - LeftMargin - RightMargin)");
            }

            // 自动分配列宽
            float autoWidth = (Report.Width - fixCols.Sum(p => (float?)p.ColumnWidth).GetValueOrDefault()) / (data.Columns.Count - fixCols.Count) - 0.01f;
            var currentNamePrefix = _reportItemPatterns.Count + _reportHeadPatterns.Count + 1;
            foreach (DataColumn column in data.Columns)
            {
                var textAlign = TextAlign.Right;
                float columnWidth = autoWidth;
                var reportColumnStyle = coloumStyle.FirstOrDefault(r => r.ColumnName == column.ColumnName);

                // 手动设置列宽优先级高
                if (reportColumnStyle != null)
                {
                    textAlign = reportColumnStyle.TextAlign;
                    // 列宽指定为0 或 不指定 则自动分配列宽
                    if (reportColumnStyle.ColumnWidth != 0f)
                        columnWidth = reportColumnStyle.ColumnWidth;
                }

                tableWidth += columnWidth;
                var bottomBorder = string.Empty; //每个单元格底部border
                if (data.Rows.Count == 0)
                {
                    bottomBorder = "<BottomBorder><Style>None</Style></BottomBorder>";
                }

                var coloumValue = column.ColumnName;
                // 例外,如果coloumName包含Coloum之类的字段,则将value设成空
                if (column.ColumnName.IndexOf("Column", System.StringComparison.Ordinal) > -1)
                {
                    coloumValue = "　";
                }

                fields.AppendFormat(fieldsTemp, column.ColumnName);
                columns.AppendFormat("<TablixColumn><Width>{0}cm</Width></TablixColumn>", columnWidth);
                tablixHearders.AppendFormat(tablixHeaderTemp, column.ColumnName, currentNamePrefix, coloumValue, bottomBorder, "黑体", "false");
                tablixCells.AppendFormat(tablixCellTemp, column.ColumnName, currentNamePrefix, textAlign, "黑体");
                tablixMembers.AppendFormat("<TablixMember />");
            }

            //计算表格应该离左边多少距离
            float leftPosition = 0F;
            if (tableWidth < Report.Width)
            {
                leftPosition = (Report.Width - tableWidth) / 2;
                if (leftPosition < 0.01f)
                    leftPosition = 0f;
            }

            var dataSetName = string.Format("Data{0}", _reportItemPatterns.Count + _reportHeadPatterns.Count + 1);
            var reportItemPattern = new ReportItemPattern();
            reportItemPattern.Data = DynamicReportExtension.RemoveZeroData(data);
            reportItemPattern.DataSetName = dataSetName;

            reportItemPattern.DataSetString = reportItemPattern.DataSetPattern
                                 .Replace("@DataSetName", dataSetName)
                                 .Replace("@Fields", fields.ToString());

            reportItemPattern.TablixString = reportItemPattern.TablixPattern
                                 .Replace("@DataSetName", dataSetName)
                                 .Replace("@TablixColumns", columns.ToString())
                                 .Replace("@TablixHeader", tablixHearders.ToString())
                                 .Replace("@TablixCells", tablixCells.ToString())
                                 .Replace("@TablixMember", tablixMembers.ToString())
                                 .Replace("@TopPosition", (0.1f).ToString())
                                 .Replace("@LeftPostion", leftPosition.ToString());

            //读取行数,如果是空行就加到新的
            if (data.Rows.Count == 0)
            {
                _reportHeadPatterns.Add(reportItemPattern);
            }
            else
            {
                _reportItemPatterns.Add(reportItemPattern);
            }
        }

        //public override string ToString()
        //{
        //    AddReportItem();
        //}

    }
}